﻿using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Mbs.ComponentModel.Container.Context;
using Mbs.Reflection;

namespace Mbs.ComponentModel.Container.Injection
{
    public class PropertyInspect : InspectAdapter<PropertyInfo>
    {
        protected const BindingFlags Flags = BindingFlags.SetProperty | BindingFlags.Instance | BindingFlags.Public;

        protected override IInjectContext<PropertyInfo> DoExecute(IInspectContext ctx)
        {
            var items = (from p in ctx.Instance.GetType().GetProperties(Flags)
                         let ps = p.GetIndexParameters()
                         let att = p.GetAttribute<InjectAttribute>(false)
                         let ignoreAtt = p.GetAttribute<IgnoreInjectAttribute>(false)
                         let id = att != null ? att.Id : string.Empty
                         where ignoreAtt == null && Filter(att, p, ps)
                         select new KeyValuePair<PropertyInfo, string>(p, id)
                       ).ToArray();

            return new InjectContext<PropertyInfo>(Kernel, ctx.Component, ctx.Instance, items);
        }

        protected virtual bool Filter(InjectAttribute att, PropertyInfo p, ParameterInfo[] ps)
        {
            if (ps != null && ps.Length > 0)
                return false;
            if (att == null)
                return false;

            if (!string.IsNullOrEmpty(att.Id))
                return Kernel.HasRegister(att.Id);

            return Kernel.HasRegister(p.PropertyType);
        }
    }
}
